<?php
/**
 * Zhub - A PHP Framework For API Developer
 *
 * This file is part of the Zhub package.
 *
 * (c) YiLong Fan <fantiq@163.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @author fanyilong <fantiq@163.com>
 * @copyright 2017 fanyilong. All rights reserved.
 * @package Zhub
 * @date 18-3-6
 */

namespace Zhub\DataBase\Query;

use Closure;
use Zhub\DataBase\Tables\Field;
use Zhub\Utils\Num;

class Condition
{
    const EQ = '=';

    const NEQ = '<>';

    const GT = '>';

    const LT = '<';

    const GE = '>=';

    const LE = '<=';

    const AND = 'AND';

    const OR = 'OR';

    const END = 0;

    private $expresses = [];

    public $parameters = [];

    public function __construct()
    {
    }

    public function exp(Field $field, $operate, $value, $logic = 0)
    {
        $this->expresses[] = ($logic ? $logic . ' ' : '') .
            "$field $operate :$field";
        // 类型检查
        $this->parameters[":$field"] = $field->isString() ? strval($value) : Num::toNumber($value);
        return $this;
    }

    public function and(Field $field, $operate, $value)
    {
        return $this->exp($field, $operate, $value, self::AND);
    }

    public function or(Field $field, $operate, $value)
    {
        return $this->exp($field, $operate, $value, self::OR);
    }

    public function andGroup(Closure $closure)
    {
        $group = clone $this;
        call_user_func($closure, $group);
        $this->expresses[] = self::AND . " ($group)";
        return $this;
    }

    public function orGroup(Closure $closure)
    {
        $group = clone $this;
        call_user_func($closure, $group);
        $this->expresses[] = self::OR . " ($group)";
        return $this;
    }

    public function clear()
    {
        $this->expresses = [];
    }

    public function __toString():string
    {
        $where = '';
        foreach ($this->expresses as $express) {
            $where .= $express . ' ';
        }
        return trim($where);
    }

    public function __clone()
    {
        $this->clear();
    }
}
